﻿/* Copyright (c) 2015 Slava Naumenko - http://m4w.codeplex.com */

using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;
using Microsoft.SharePoint.WorkflowServices;
using System;
using System.Collections.Generic;
using System.Web.Services;

namespace M4W.ASM.Services
{
    [WebService(Namespace = "M4W.ASM.Services")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.Web.Script.Services.ScriptService]
    [System.ComponentModel.ToolboxItem(false)]
    public class List : System.Web.Services.WebService
    {
        [WebMethod]
        public string WorkflowStart(string Workflow, string List, string ItemId)
        {
            string result = "";
            try
            {
                result = ListWorkflowStart.Invoke(Workflow, List, ItemId);
            }
            catch (Exception ex)
            {
                result = ex.Message.ToString();
            }
            return result;
        }
    }

    // Invocations

    internal static class ListWorkflowStart
    {
        internal static string Invoke(string Workflow, string List, string ItemId)
        {
            string result = "";

            string curl = Helper.GetCurrentUrl();

            using (SPSite site = new SPSite(curl))
            {
                using (SPWeb web = site.OpenWeb())
                {
                    web.AllowUnsafeUpdates = true;

                    SPList list = Helper.GetList(web, List);
                    if (list == null) { throw new Exception("List '" + List + "' not found."); }

                    SPListItem listItem = list.Items.GetItemById(Int16.Parse(ItemId));

                    string mode = "";

                    // 2010

                    SPWorkflowAssociation workflowAssociation = list.WorkflowAssociations.GetAssociationByName(Workflow, System.Threading.Thread.CurrentThread.CurrentCulture);
                    if (workflowAssociation == null)
                    {
                        foreach (SPContentType contentType in list.ContentTypes)
                        {
                            workflowAssociation = contentType.WorkflowAssociations.GetAssociationByName(Workflow, System.Threading.Thread.CurrentThread.CurrentCulture);
                            if (workflowAssociation != null) { break; }
                        }
                    }

                    // 2013

                    WorkflowServicesManager workflowServicesManager = new Microsoft.SharePoint.WorkflowServices.WorkflowServicesManager(web);
                    WorkflowSubscription workflowSubscription = null;

                    if (workflowAssociation != null)
                    {
                        mode = "2010";
                    }
                    else
                    {
                        foreach (WorkflowSubscription subscription in workflowServicesManager.GetWorkflowSubscriptionService().EnumerateSubscriptionsByList(list.ID))
                        {
                            if (subscription.Name == Workflow)
                            {
                                workflowSubscription = subscription;
                                break;
                            }
                        }

                        if (workflowSubscription != null)
                        {
                            mode = "2013";
                        }
                    }

                    bool itemWorkflowStarted = false;

                    switch (mode)
                    {
                        case "2010":
                            foreach (SPWorkflow workflowRunningInstance in listItem.Workflows)
                            {
                                if (!workflowRunningInstance.IsCompleted && workflowRunningInstance.AssociationId == workflowAssociation.Id)
                                {
                                    itemWorkflowStarted = true;
                                    break;
                                }
                            }

                            if (!itemWorkflowStarted)
                            {
                                site.WorkflowManager.StartWorkflow(listItem, workflowAssociation, workflowAssociation.AssociationData, SPWorkflowRunOptions.Asynchronous);
                                result = "2010 workflow '" + Workflow + "' started on '" + List + "'" + " item '" + ItemId + "'.";
                            }
                            else
                            {
                                result = "2010 workflow '" + Workflow + "' is already running on '" + List + "'" + " item '" + ItemId + "'.";
                            }
                            break;
                        case "2013":
                            WorkflowInstanceService workflowInstanceService = workflowServicesManager.GetWorkflowInstanceService();

                            foreach (WorkflowInstance workflowInstance in workflowInstanceService.EnumerateInstancesForListItem(list.ID, listItem.ID))
                            {
                                if (workflowInstance.Status == WorkflowStatus.Started && workflowInstance.WorkflowSubscriptionId == workflowSubscription.Id)
                                {
                                    itemWorkflowStarted = true;
                                    break;
                                }
                            }

                            if (!itemWorkflowStarted)
                            {
                                workflowInstanceService.StartWorkflowOnListItem(workflowSubscription, listItem.ID, new Dictionary<string, object>());
                                result = "2013 workflow '" + Workflow + "' started on '" + List + "'" + " item '" + ItemId + "'.";
                            }
                            else
                            {
                                result = "2013 workflow '" + Workflow + "' is already running on '" + List + "'" + " item '" + ItemId + "'.";
                            }
                            break;
                        default:
                            result = "Workflow '" + Workflow + "' could not be found on '" + List + "'.";
                            break;
                    }

                    web.AllowUnsafeUpdates = false;
                }
            }

            return result;
        }
    }
}